package com.learn.sb.sblearnshardingjdbc.strategy;

import com.google.common.collect.Range;
import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.RangeShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import io.shardingjdbc.core.api.algorithm.sharding.standard.RangeShardingAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class LogassetTableShardingAlgorithm implements PreciseShardingAlgorithm<Integer>, RangeShardingAlgorithm<Integer> {

	@Override
	public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Integer> rangeShardingValue) {
		log.info("Range collection:" + availableTargetNames + ",rangeShardingValue:" + rangeShardingValue);
		Collection<String> collect = new ArrayList<>();
		Range<Integer> valueRange = rangeShardingValue.getValueRange();
		for (String logicTable : availableTargetNames) {
			log.info(logicTable);
			collect.addAll(actualDataNodes(logicTable, valueRange.lowerEndpoint(), valueRange.upperEndpoint()));
		}
		return collect;
	}

	@Override
	public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> preciseShardingValue) {
		try {
			for (String logicTable : availableTargetNames) {
				log.info(logicTable);
				for(String name : actualDataNodes(logicTable, null, null)) {
					if (name.endsWith(calcYyyyyMm(preciseShardingValue.getValue()))) {
						return name;
					}
				}
			}
		} catch (Exception e) {
			log.error("", e);
		}
		return null;
	}

	public List<String> actualDataNodes(String logicTable, Integer beginYyyymmdd, Integer endYyyymmdd) {
		Integer START_DATE = 20190101;
		List<String> list = new ArrayList<>();
		try {
			Date startDate = new SimpleDateFormat("yyyyMMdd").parse(START_DATE.toString());
			if (null != beginYyyymmdd && beginYyyymmdd > START_DATE)
				startDate = new SimpleDateFormat("yyyyMMdd").parse(beginYyyymmdd.toString());
			Date endDate = new Date();
			if (null != endYyyymmdd) {
				Date endYyyymmddDate = new SimpleDateFormat("yyyyMMdd").parse(endYyyymmdd.toString());
				if (endYyyymmddDate.compareTo(endDate) < 0) {
					endDate = endYyyymmddDate;
				}
			}
			Calendar index = Calendar.getInstance();
			index.setTime(startDate);
			while (index.getTime().compareTo(endDate) < 0) {
				list.add(logicTable + (new SimpleDateFormat("_yyyy_MM").format(index.getTime())));
				index.add(Calendar.MONTH, 1);
			}
		} catch (Exception e) {
			log.error("", e);
		}
		return list;
	}


	private String calcYyyyyMm(Integer bizdate) throws Exception {
		SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
		SimpleDateFormat yyyy_MM = new SimpleDateFormat("_yyyy_MM");
		Date date = yyyyMMdd.parse(bizdate.toString());
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		String postFix = yyyy_MM.format(calendar.getTime());
		return postFix;
	}

	public static void main(String[] args) throws Exception {
		System.out.println(new LogassetTableShardingAlgorithm().calcYyyyyMm(20190901));
		System.out.println(new LogassetTableShardingAlgorithm().actualDataNodes("t_logasset", null, null));
		System.out.println(new LogassetTableShardingAlgorithm().actualDataNodes("t_logasset", 20190201, 20190505));
	}
}
